home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 21
/
Cream of the Crop 21 (Terry Blount) (October 1996).iso
/
os2
/
fst03f.zip
/
fst.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-08-12
|
41KB
|
1,560 lines
/* fst.c -- Main module of fst
Copyright (c) 1995-1996 by Eberhard Mattes
This file is part of fst.
fst is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
fst is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with fst; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define INCL_DOSDEVIOCTL
#define INCL_DOSNLS
#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "fst.h"
#include "crc.h"
#include "diskio.h"
#include "fat.h"
#include "do_hpfs.h"
#include "do_fat.h"
static char banner[] =
"fst 0.3f -- Copyright (c) 1995-1996 by Eberhard Mattes\n";
/* Increase the heap for -Zsys to 64MB. */
unsigned _sys_heap_size = 0x4000000;
char verbose; /* Non-zero for `check -v' and `save -v' */
char sector_number_format; /* 'x' for `-x', 0 otherwise */
char a_info; /* Non-zero for `info' action */
char a_save; /* Non-zero for `save' action */
char a_check; /* Non-zero for `check' action */
char a_what; /* Non-zero for `info <number>' action */
char a_where; /* Non-zero for `info <path>' action */
char a_copy; /* Non-zero for `copy' action */
char a_dir; /* Non-zero for `dir' action */
char a_find; /* Non-zero for finding a file */
char plenty_memory; /* Non-zero for `check -m' */
char check_unused; /* Non-zero for `check -u' */
char check_pedantic; /* Non-zero for `check -p' */
char show_unused; /* Non-zero for `info -u' */
char show_free_frag; /* Non-zero for `info -f' */
char show_frag; /* Non-zero for `check -f' */
char show_eas; /* Non-zero for `info -e <path>' */
char show_summary; /* Non-zero for `check -s' */
char force_fs; /* Non-zero to force to a specific fs */
ULONG what_sector; /* Sector number for `info <number>' action */
char what_cluster_flag; /* `what_sector' is a cluster number */
const char *find_path; /* (Remainder of) pathname for a_find */
/* This table maps lower-case letters to upper case, using the current
code page. */
BYTE cur_case_map[256];
FILE *diag_file; /* Stream for diagnostics */
FILE *prog_file; /* Stream for progress report */
static FILE *info_file; /* Stream for information */
static int warning_count[2]; /* Index 0: warnings, index 1: errors */
static char list_going; /* Non-zero if list started */
static int list_x; /* Column */
static char list_msg[80]; /* Message */
/* path_chain_new() tries to avoid malloc()'s memory overhead by
allocating reasonably big buffers out of which the strings and
path_chains will be allotted. Fortunately, we never free those
structures. */
struct str_buf
{
char *buf;
size_t size;
size_t used;
struct str_buf *next;
};
struct str_buf *str_buf_head;
static path_chain *pc_buf;
static size_t pc_count;
static size_t pc_used;
/* Clean up and terminate the process. RC is the return code passed
to the parent process. If SHOW is non-zero, show the number of
warnings and errors even if both numbers are zero. */
void quit (int rc, int show)
{
if (save_file != NULL)
{
fclose (save_file);
save_file = NULL;
remove (save_fname);
}
if (warning_count[0] != 0 || warning_count[1] != 0 || show)
fprintf (stdout, "Total warnings: %d, total errors: %d\n",
warning_count[0], warning_count[1]);
if (rc == 0 && warning_count[1] != 0)
rc = 1;
exit (rc);
}
/* Treat `#%lu' in FMT as format specifiers for sector numbers. We
cannot introduce our own format specifier (such as `%N') because
that would cause loads of GCC warnings or we would loose checking
of format strings. */
static void adjust_format_string (char *dst, const char *src)
{
while (*src != 0)
if (src[0] != '#' || src[1] != '%' || src[2] != 'l' || src[3] != 'u')
*dst++ = *src++;
else
{
src += 4;
switch (sector_number_format)
{
case 'x':
*dst++ = '0'; *dst++ = 'x'; *dst++ = '%';
*dst++ = '.'; *dst++ = '8'; *dst++ = 'l'; *dst++ = 'x';
break;
default:
*dst++ = '%'; *dst++ = 'l'; *dst++ = 'u';
break;
}
}
*dst = 0;
}
/* Like vfprintf(), but treat #%lu specially (sector number). Return
the number of characters printed. */
int my_vfprintf (FILE *f, const char *fmt, va_list arg_ptr)
{
char new_fmt[512];
adjust_format_string (new_fmt, fmt);
return vfprintf (f, new_fmt, arg_ptr);
}
/* Like fprintf(), but treat #%lu specially (sector number). Return
the number of characters printed. */
int my_fprintf (FILE *f, const char *fmt, ...)
{
va_list arg_ptr;
char new_fmt[512];
int r;
adjust_format_string (new_fmt, fmt);
va_start (arg_ptr, fmt);
r = my_vfprintf (f, new_fmt, arg_ptr);
va_end (arg_ptr);
return r;
}
/* Like vsprintf(), but treat #%lu specially (sector number). Return
the number of characters printed. */
int my_vsprintf (char *buf, const char *fmt, va_list arg_ptr)
{
char new_fmt[512];
adjust_format_string (new_fmt, fmt);
return vsprintf (buf, new_fmt, arg_ptr);
}
/* Like sprintf(), but treat #%lu specially (sector number). Return
the number of characters printed. */
int my_sprintf (char *buf, const char *fmt, ...)
{
va_list arg_ptr;
char new_fmt[512];
int r;
adjust_format_string (new_fmt, fmt);
va_start (arg_ptr, fmt);
r = my_vsprintf (buf, new_fmt, arg_ptr);
va_end (arg_ptr);
return r;
}
/* Display a fatal error message and terminate the process. */
void error (const char *fmt, ...)
{
va_list arg_ptr;
list_end ();
fflush (info_file);
fprintf (stderr, "ERROR: ");
va_start (arg_ptr, fmt);
my_vfprintf (stderr, fmt, arg_ptr);
va_end (arg_ptr);
fputc ('\n', stderr);
warning_count[1] += 1;
quit (2, TRUE);
}
/* Common code for all functions which display warnings. Show the
severity (LEVEL) of the message and increment the appropriate
counter. */
void warning_prolog (int level)
{
list_end ();
fflush (info_file);
switch (level)
{
case 0:
fprintf (diag_file, "WARNING: ");
break;
case 1:
fprintf (diag_file, "ERROR: ");
break;
default:
abort ();
}
warning_count[level] += 1;
}
/* Common code for all functions which display warnings. This is
called after printing a message. */
void warning_epilog (void)
{
fflush (diag_file);
}
/* Display a warning of severity LEVEL (0=warning, 1=error). */
void warning (int level, const char *fmt, ...)
{
va_list arg_ptr;
warning_prolog (level);
va_start (arg_ptr, fmt);
my_vfprintf (diag_file, fmt, arg_ptr);
va_end (arg_ptr);
fputc ('\n', diag_file);
warning_epilog ();
}
/* Continue a warning. */
void warning_cont (const char *fmt, ...)
{
va_list arg_ptr;
va_start (arg_ptr, fmt);
fputs (" ", diag_file);
my_vfprintf (diag_file, fmt, arg_ptr);
va_end (arg_ptr);
fputc ('\n', diag_file);
warning_epilog ();
}
/* Display information. No linefeed is appended! Return the number
of characters printed. */
int info (const char *fmt, ..